
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Laurens
 */
public class referenceFinder 
{
    Vector<String> variable = null;
    /**
     * Constructor DOES NOTHING
     */ 
    referenceFinder()
    {
        
    }
    
    public static void main(String args[])
    {
        //referenceFinder find = new referenceFinder();
        //Vector<String> result = find.referenceFinder("refactor", "C:\\Users\\Laurens\\Documents\\NetBeansProjects\\CASE-Tool\\src", "htest");
    }
    
    /**
     * Finds the reference of oldMethod in currentDirectory
     * @param oldMethod
     * @param currentDirectory
     * @return 
     */
    public Vector<String> referenceFinder(String oldMethod, String currentDirectory, String currentClassDeclaration)
    {
        if("".equals(oldMethod))
        {
            return null;
        }
        else if("".equals(currentDirectory))
        {
            return null;
        }
        Vector<String> reference = new Vector<String>();
        String file = "";
        String s = "";
        variable = new Vector<String>();
        File path = new File(currentDirectory);
        File[] files = path.listFiles(new WildCardFileFilter("*.java"));
        Vector<String> paths = new Vector<String>();
        for(File oneFile : files)
        {
            paths.add(oneFile.toString());
        }      
        for(int y = 0; y < paths.size(); y++)
        {
            file = "";
            try
            {
                //System.out.println(paths.get(y));
                FileReader fileR = new FileReader(paths.get(y));
                BufferedReader buff = new BufferedReader(fileR);
                while((s = buff.readLine()) != null)
                {
                        file += s + "\n";
                }
                boolean check = false;
                StringTokenizer st = new StringTokenizer(file, "\n");
                while(st.hasMoreTokens() || check != true)
                {
                    String currentLine = st.nextToken();
                    if(currentLine.contains(" "+currentClassDeclaration+" "))
                    {
                        variable.add(findVaraible(currentLine));
                        check = check(oldMethod, file);
                    }
                    else if(currentLine.contains("new " +currentClassDeclaration+"("))
                    {
                        check = check(oldMethod, file);
                    }
                    else
                    {

                    }
                }
                if(check)
                {
                    reference.add(paths.get(y));
                }                      
            }
            catch(Exception e)
            {

            }
        }
        return reference;        
    }
    
        /**
     * Finds the reference of oldMethod in currentDirectory
     * @param oldMethod
     * @param currentDirectory
     * @return 
     */
    public Vector<String> referenceFinderOverloaded(String oldMethod, String currentDirectory, String currentClassDeclaration, int cParam)
    {
        if("".equals(oldMethod))
        {
            return null;
        }
        else if("".equals(currentDirectory))
        {
            return null;
        }
        Vector<String> reference = new Vector<String>();
        String file = "";
        String s = "";
        variable = new Vector<String>();
        File path = new File(currentDirectory);
        File[] files = path.listFiles(new WildCardFileFilter("*.java"));
        Vector<String> paths = new Vector<String>();
        for(File oneFile : files)
        {
            paths.add(oneFile.toString());
        }      
        for(int y = 0; y < paths.size(); y++)
        {
            file = "";
            try
            {
                //System.out.println(paths.get(y));
                FileReader fileR = new FileReader(paths.get(y));
                BufferedReader buff = new BufferedReader(fileR);
                while((s = buff.readLine()) != null)
                {
                        file += s + "\n";
                }
                boolean check = false;
                StringTokenizer st = new StringTokenizer(file, "\n");
                while(st.hasMoreTokens() || check != true)
                {
                    String currentLine = st.nextToken();
                    if(currentLine.contains(" "+currentClassDeclaration+" "))
                    {
                        variable.add(findVaraible(currentLine));
                        check = checkOverload(oldMethod, file, cParam);
                    }
                    else if(currentLine.contains("new " +currentClassDeclaration+"("))
                    {
                        check = checkOverload(oldMethod, file, cParam);
                    }
                    else
                    {

                    }
                }
                if(check)
                {
                    reference.add(paths.get(y));
                }                      
            }
            catch(Exception e)
            {

            }
        }
        return reference;        
    }
    
    public boolean check(String oldMethod, String file)
    {
        boolean result = false;
        StringTokenizer st = new StringTokenizer(file, "\n");
        String currentLine = " ";
        Vector<String> spaces = new Vector<String>();
        spaces.add("");
        spaces.add(" ");
        spaces.add("  ");
        spaces.add("   ");
        spaces.add("    ");
        spaces.add("     ");
        spaces.add("      ");
        spaces.add("       ");
        while(st.hasMoreTokens())
        {
            currentLine = st.nextToken();
            for(int u = 0; u < spaces.size(); u++)
            {
                if(currentLine.contains("."+oldMethod+spaces.get(u)+"("))
                {
                    result = true;
                }
            }
        }
        return result;
    }
    
    public boolean checkOverload(String oldMethod, String file, int paramNum)
    {
        boolean result = false;
        StringTokenizer st = new StringTokenizer(file, "\n");
        String currentLine = " ";
        Vector<String> spaces = new Vector<String>();
        spaces.add("");
        spaces.add(" ");
        spaces.add("  ");
        spaces.add("   ");
        spaces.add("    ");
        spaces.add("     ");
        spaces.add("      ");
        spaces.add("       ");
        while(st.hasMoreTokens())
        {
            currentLine = st.nextToken();
            for(int u = 0; u < spaces.size(); u++)
            {
                if(currentLine.contains("."+oldMethod+spaces.get(u)+"("))
                {
                    if(parameters(currentLine) == paramNum)
                    {
                        result = true;
                        u = spaces.size();
                    }
                    else
                    {
                        
                    }
                }
                else
                {
                    
                }
            }
        }
        return result;
    }
    
    public String findVaraible(String currentLine)
    {
        String result = " ";
        StringTokenizer current = new StringTokenizer(currentLine, " ");
        result = current.nextToken();
        result = current.nextToken();
        //System.out.println(result);
        return result;
    }
    
    public Vector<String> getVariableNames(String className, String replacingClassName, String contents)
    {
        Vector<String> varNames = new Vector<String>();
        Scanner st = new Scanner(contents);
        String current ="";
        String finalstr = "";
        boolean fb = true;
        boolean bc = true;
        boolean quoteFlag = true;
        boolean found = false;
        int counter = 0;
        while(st.hasNext())
        {
            finalstr = "";
            current = st.nextLine();
            if(current.length() >= 2 && current.trim().length() >= 2 && current.trim().substring(0, 2).equals("//"))
            {
            }
            else
            {

                for(int i = 0; i < current.length() ;i++)
                {
                    if(current.length() >= i+2 && current.substring(i,i+2).equals("/*") && fb == true && quoteFlag == true)
                    {
                        fb = false;
                        quoteFlag = false;
                        bc = false;
                    }


                    if(current.length() >= i+2 && current.substring(i,i+2).equals("*/"))
                    {
                        fb = true;
                        quoteFlag = true;
                        bc = true;
                        i++;
                        i++;
                    }
                    if(i < current.length() && current.length() >= i+2 && current.substring(i,i+2).equals("/*") && quoteFlag == true)
                    {
                        fb = false;
                    }
                    if(counter == 2)
                        quoteFlag = true;
                    if(i < current.length() && current.charAt(i) == '"' && fb == true)
                    {
                        if(current.charAt(i-1) != '\\')
                                counter++;
                        quoteFlag = false;
                    }



                    if(current.length() >= i+2 && current.substring(i,i+2).equals("//") && bc == true && quoteFlag == true)
                    {
                        break;
                    }                   
                    if(i < current.length() &&fb == true && quoteFlag == true && bc == true)
                    {
                        finalstr+= current.charAt(i);
                    }
                    

                }
                
                //System.out.println(finalstr);
                if(finalstr.contains(className))
                {
                    StringTokenizer tk = new StringTokenizer(finalstr);
                    String holder = "";
                    while(tk.hasMoreTokens())
                    {
                        holder = tk.nextToken();
                        if(found == true)
                        {
                            if(holder.contains("="))
                            {
                                varNames.add(holder.substring(0, holder.indexOf("=")));
                            }
                            else
                            {
                                String temp = "";
                                for(int j = 0;j < holder.length() && holder.charAt(j) != ';' ;j++)
                                {
                                    if(holder.charAt(j) == ',')
                                    {
                                        varNames.add(temp);
                                        temp = "";
                                    }
                                    else
                                        temp += holder.charAt(j);
                                }
                                varNames.add(temp);
                            }
                            
                            found = false;
                            
                        }
                        
                        
                        if(holder.equals(className))
                        {
                            //System.out.println("in");
                            found = true;
                        }
                    }
                }
            }
        }
        return varNames;
    }
    
    public String renameMethod(String contents,Vector<String> vars,Vector<String> oldMethodName,Vector<String> newMethodName)
    {
        String content = "";
        Scanner st = new Scanner(contents);
        String current ="";
        while(st.hasNext())
        {
            current = st.nextLine();
            String tempContent = current;
            for(int i = 0; i < vars.size() ; i++)
            {
                for(int j = 0; j < oldMethodName.size() ;j++ )
                {
                    String temp = vars.get(i)+"."+oldMethodName.get(j);
                    if(current.contains(temp))
                    {
                        tempContent = tempContent.replace(temp, vars.get(i)+"."+newMethodName.get(j)) + "\n";
                    }
                }
            }

                content += tempContent + "\n";

        }
        return content;

    }
    
    public String renameConstructor(String className,String newName,String contents)
    {
        Stack<String> bStack = new Stack<String>();
        Scanner st = new Scanner(contents);
        String current ="";
        String newContent = "";
        String parameters = "";
        String finalstr = "";
        String var = "";
        int start = 0;
        int end = 0;
        boolean fb = true;
        boolean cns = false;
        boolean bc = true;
        boolean quoteFlag = true;
        int counter = 0;
        while(st.hasNext())
        {
            finalstr = "";
            cns = false;
            current = st.nextLine();
            end = 0;
            start = 0;
            if(current.length() >= 2 && current.trim().length() >= 2 && current.trim().substring(0, 2).equals("//"))
            {
                
            }
            else
            {
                int lastindex = 0;
                for(int i = 0; i < current.length() ;i++)
                {
                    
                    if(current.length() >= i+2 && current.substring(i,i+2).equals("/*") && fb == true && quoteFlag == true)
                    {
                        fb = false;
                        quoteFlag = false;
                        bc = false;
                    }


                    if(current.length() >= i+2 && current.substring(i,i+2).equals("*/"))
                    {
                        fb = true;
                        quoteFlag = true;
                        bc = true;
                        i++;
                        i++;
                    }
                    if(i < current.length() && current.length() >= i+2 && current.substring(i,i+2).equals("/*") && quoteFlag == true)
                    {
                        fb = false;
                    }
                    if(counter == 2)
                        quoteFlag = true;
                    if(i < current.length() && current.charAt(i) == '"' && fb == true)
                    {
                        if(current.charAt(i-1) != '\\')
                                counter++;
                        quoteFlag = false;
                    }



                    if(current.length() >= i+2 && current.substring(i,i+2).equals("//") && bc == true && quoteFlag == true)
                    {
                        break;
                    }                   
                    if(i < current.length() &&fb == true && quoteFlag == true && bc == true)
                    {
                        finalstr+= current.charAt(i);
                    }
                    
                    if(finalstr.substring(lastindex,finalstr.length()).contains(className+"("))
                    {
                        //System.out.println(finalstr);
                        if(finalstr.charAt(finalstr.length()-1) == '(')
                        {
                            cns = true;
                            start = i;
                            
                        }
                    }
                    
                    if(cns == true && i < finalstr.length())
                    {
                        parameters += finalstr.charAt(finalstr.length() - 1);
                        if(finalstr.charAt(finalstr.length() - 1) == '(')
                        {
                            //System.out.println(finalstr.charAt(finalstr.length() - 1));
                            bStack.push("(");
                        }
                        if(finalstr.charAt(finalstr.length() - 1) == ')')
                        {
                            bStack.pop();
                            if(bStack.empty())
                            {
                                cns = false;
                                end = i;
                                lastindex = 0;
                                
                                StringTokenizer token = new StringTokenizer(current.substring(0,current.indexOf("=")));
                                while(token.hasMoreTokens())
                                {
                                    var = token.nextToken();
                                }
                            }
                        }
                    }

                }
            }
            
            if(end != 0)
            {
                newContent += current.substring(0,start+1);
                if(end > 0 && end < current.length())
                {
                    newContent += current.substring(end,current.length());
                }
                newContent += "\n";
                newContent += var + "." + className+"infinitysolutions"+ parameters + ";\n";
            }
            else
            {
                newContent += current + "\n";
            }
        }
        st = new Scanner(newContent);
        newContent = "";
        while(st.hasNext())
        {
            current = st.nextLine();
            if(current.contains(className+"infinitysolutions"))
            {
                newContent += current.replaceAll(className+"infinitysolutions", className) +"\n";
            }
            else
                newContent += current.replaceAll(className, newName) +"\n";
        }
        
    return newContent;
    }
    
    public String renameField(String contents,Vector<String> vars,Vector<String> oldFieldName,Vector<String> newFieldName)
    {
        String content = "";
        Scanner st = new Scanner(contents);
        String current ="";
        while(st.hasNext())
        {
            current = st.nextLine();
            String tempContent = current;
            for(int i = 0; i < vars.size() ; i++)
            {
                for(int j = 0; j < oldFieldName.size() ;j++ )
                {
                    String temp = vars.get(i)+"."+oldFieldName.get(j);
                    if(current.contains(temp))
                    {
                        if(!current.contains(temp+"("))
                            tempContent = tempContent.replace(temp, vars.get(i)+"."+newFieldName.get(j)) + "\n";
                    }
                }
            }
            content += tempContent + "\n";
           
        }
        return content;
    }

    Vector referenceFinderOverload(String oldMethod, String currentDirectory, String currentClassDeclaration, int cParam) 
    {
        if("".equals(oldMethod))
        {
            return null;
        }
        else if("".equals(currentDirectory))
        {
            return null;
        }
        Vector<String> reference = new Vector<String>();
        String file = "";
        String s = "";
        variable = new Vector<String>();
        File path = new File(currentDirectory);
        File[] files = path.listFiles(new WildCardFileFilter("*.java"));
        Vector<String> paths = new Vector<String>();
        for(File oneFile : files)
        {
            paths.add(oneFile.toString());
        }      
        for(int y = 0; y < paths.size(); y++)
        {
            file = "";
            try
            {
                //System.out.println(paths.get(y));
                FileReader fileR = new FileReader(paths.get(y));
                BufferedReader buff = new BufferedReader(fileR);
                while((s = buff.readLine()) != null)
                {
                        file += s + "\n";
                }
                boolean check = false;
                StringTokenizer st = new StringTokenizer(file, "\n");
                while(st.hasMoreTokens() || check != true)
                {
                    String currentLine = st.nextToken();
                    if(currentLine.contains(" "+currentClassDeclaration+" "))
                    {
                        check = checkOverload(oldMethod, file, cParam);
                    }
                    else if(currentLine.contains("new " +currentClassDeclaration+"("))
                    {
                        check = checkOverload(oldMethod, file, cParam);
                    }
                    else
                    {

                    }
                }
                if(check)
                {
                    reference.add(paths.get(y));
                }                      
            }
            catch(Exception e)
            {

            }
        }
        return reference;        
    }
    
    private int parameters(String currentLine) 
    {
        int output = 0;
        StringTokenizer st = new StringTokenizer(currentLine, "(");
        st.nextToken();
        String current = "";
        while(st.hasMoreTokens())
        {
            current += st.nextToken();
        }
        String noBrackets = current.trim().substring(0, current.length() - 1);
        if(noBrackets.trim().isEmpty())
        {
            return output;
        }
        else
        {
            output++;
        }
        StringTokenizer st2 = new StringTokenizer(noBrackets);
        while(st2.hasMoreTokens())
        {
            String current2 = st2.nextToken();
            if(current2.contains(","))
            {
                output++;
            }
        }
        return output;
    }
}
